import { stringify } from "./common"
/**
 * @from https://github.com/e-kit/ekit/blob/master/packages/ajax/src/new-ajax.ts
 */

/** 不再兼容非标准的数据结构 */
export declare type AjaxPromise<R> = Promise<R>;

export interface ExtraFetchParams {
    /** extra data for extends */
    extra?: RequestInit;
    /** 扩展请求头 */
    headers?: Record<string, string>;
    /** cancel request */
    cancel?: Promise<string | undefined>;
}

export interface WrappedFetchParams extends ExtraFetchParams {
    /** http method */
    method: "GET" | "POST" | "PUT" | "DELETE" | "OPTIONS" | "PATCH" | "HEAD";
    url: string;
    /** post json data */
    data?: object;
    /** post form data */
    form?: object | FormData;
    /** query data */
    query?: object;
    /** header */
    header?: Record<string, string>;
    /** path data */
    path?: string;
}

/** ajax 方法 */
const ajax = async (
    {
        method, url, data, form, query, header, extra, headers
    }: WrappedFetchParams
) => {
    let config: RequestInit = {
        ...extra,
        method: method.toLowerCase(),
        headers: { ...headers, ...header }
    }
    // json
    if (data) {
        config = {
            ...config,
            headers: {
                // 可覆盖
                "Content-Type": "application/json",
                ...config.headers
            },
            body: JSON.stringify(data)
        }
    }
    // form
    if (form) {
        config = {
            ...config,
            headers: {
                // 可覆盖
                "Content-Type": "application/x-www-form-urlencoded",
                ...config.headers
            },
            body: (
                form instanceof FormData ? form : stringify(form)
            )
        }
    }
    return fetch(query ? `${url}?${stringify(query)}` : url, {
        ...config
    })
        .then((res) => res.json())
}

/** 接口传参校验 */
const check = function check<V>(value: V, name: string) {
    if (value === null || value === undefined) {
        const msg = `[ERROR PARAMS]: ${name} can't be null or undefined`
        throw Error(msg)
    }
}

export default {
    ajax, check
}
